#!/usr/bin/env perl
use warnings;
use strict;

use DBI;
use CGI;

# includes should already be defined globally
BEGIN { require(INCLUDES . '/functions.pl'); }

# change this to something long and random (must be the same on both servers)
use constant SHARED_SECRET => 'CHANGE ME IMMEDIATELY';

# modify to suit your setup
# DOMAIN should be your low-bandwidth domain name (no www.)
use constant DOMAIN      => 'mydomain.com';
use constant HBW_IMG_URL => 'http://www.myotherdomain.com/images';
use constant LBW_IMG_URL => 'http://www.mydomain.com/images';

# you probably don't need to change these
use constant HBW_UPLOAD => HBW_IMG_URL . '/upload.pl';
use constant LBW_UPLOAD => LBW_IMG_URL . '/upload.pl';
use constant HBW_MODIFY => HBW_IMG_URL . '/modify.pl';
use constant LBW_MODIFY => LBW_IMG_URL . '/modify.pl';
use constant CURL => 'curl';

# please don't change: copyright and version info
use constant COPYRIGHT => 'ai Image Uploader v3.0, &copy; 2006-2007 Robert Weispfenning';
use constant USERAGENT => 'aiImageUploader/3.0';


# returns a filename with any illegal characters stripped out
sub sanitize_filename($) {
    my ($fname) = @_;

    # filenames consist of lowercase letters, numbers, underscores, dots,
    # hyphens, and cannot begin with a dot
    $fname =~ tr/A-Z/a-z/;
    $fname =~ tr/ /_/;
    $fname =~ s/[^a-z0-9_.\-]//g;
    $fname =~ s/^\.+//;

    return $fname;
}

# returns an html page title with any illegal characters stripped out
sub sanitize_title($) {
    my ($title) = @_;

    $title =~ s/&/&amp;/g;
    $title =~ s/"/&quot;/g;
    $title =~ s/</&lt;/g;
    $title =~ s/>/&gt;/g;

    return $title;
}

# returns the correct thumbnail name for a given filename
sub get_thumbname($) {
    my ($fname) = @_;

    return substr($fname, 0, -4) . '-th' . substr($fname, -4, 4);
}

# gets information about an image using ImageMagick's identify command
sub get_image_info($) {
    my ($fname) = @_;

    # filename better be sanitized if it's going to be run in a command
    $fname = sanitize_filename($fname);
    my @identify = split(/ /, `identify $fname`);
    my $type = $identify[1];
    if ($type ne 'GIF' and $type ne 'JPEG' and $type ne 'PNG') {
        return ($type, 0, 0, 0);
    }

    my ($width, $height) = split(/x/, $identify[2]);
    my $size = (-s $fname);

    return ($type, $width, $height, $size);
}

# generates a thumbnail using ImageMagick's convert command
sub make_thumbnail($$$$) {
    my ($fname, $type, $width, $height) = @_;

    # sanitize input that will be used in command
    $fname = sanitize_filename($fname);
    $width = int($width);
    $height = int($height);

    $fname .= '[0]' if ($type eq 'GIF');
    my $thumbname = get_thumbname($fname);

    # create correct thumbnail dimensions
    my $dimensions = $width . 'x' . $height;
    $dimensions = '250x250' if ($width > 250 or $height > 250);

    # execute call to ImageMagick
    system("convert $fname -thumbnail $dimensions -quality 80 $thumbname");

    return $thumbname;
}

# returns the current page and total number of pages
sub get_page_info($$) {
    my ($dbh, $cgi) = @_;

    # get total number of images from database
    my $image_total = 0;
    my $sth = $dbh->prepare("SELECT COUNT(*) FROM images");
    $sth->execute();
    while (my @result = $sth->fetchrow_array()) {
        $image_total = $result[0];
    }
    $sth->finish();

    # calculate total number of pages (16 images per page)
    my $page_total = int($image_total / 16);
    $page_total += 1 if ($image_total / 16 - $page_total > 0);
    $page_total = 1 if ($page_max < 1);

    # get current page from cgi
    my $page = 1;
    if (defined($cgi->param('page'))) {
        $page = int($cgi->param('page'));
        $page = $page_total if ($page > $page_total);
        $page = 1 if ($page < 1);
    }

    return ($page, $page_total);
}

# returns information about an image from the database
sub get_image_data($$) {
    my ($dbh, $id) = @_;

    my ($hash, $name, $fname, $thumb, $width, $height, $size);
    my $sth = $dbh->prepare("SELECT * FROM images WHERE id = ?");
    $sth->execute($id);
    while (my $result = $sth->fetchrow_hashref()) {
        $hash   = $result->{'hash'};
        $name   = $result->{'name'};
        $fname  = $result->{'filename'};
        $thumb  = $result->{'thumbnail'};
        $width  = int($result->{'width'});
        $height = int($result->{'height'});
        $size   = int($result->{'size'});
    }
    $sth->finish();

    return ($hash, $name, $fname, $thumb, $width, $height, $size);
}

# returns whether an image hash exists in the database or not
sub is_repeat($$) {
    my ($dbh, $hash) = @_;

    my $is_repeat = 0;
    my $sth = $dbh->prepare("SELECT hash FROM images WHERE hash = ?");
    $sth->execute($hash);
    while ($sth->fetchrow_array()) {
        $is_repeat = 1;
    }
    $sth->finish();

    return $is_repeat;
}

# prints statistics about the gallery
sub print_stats($$) {
    my ($dbh, $cgi) = @_;
    my $copyright = COPYRIGHT;

    # get image stats
    my ($image_total, $size_total);
    my $sth = $dbh->prepare("SELECT COUNT(*), SUM(size) FROM images");
    $sth->execute();
    while (my @result = $sth->fetchrow_array()) {
        ($image_total, $size_total) = @result;
        if (not defined($size_total)) {
            $image_total = 0;
            $size_total = 0;
        }
        $size_total = pretty_size($size_total);
    }
    $sth->finish();

    # get the user's browser useragent
    my $ua = $cgi->user_agent;

    print <<END;
        <hr />
        <p>
            Database: $image_total images in $size_total<br />
            User-agent: $ua<br />
            $copyright
        </p>
END
}

# parses a behind-the-scenes response from one server to the other
sub parse_response(@) {
    my (@response) = @_;
    my $status;

    foreach (@response) {
        next unless ($_ =~ /<h1>/);

        if    ($_ =~ /Success/)            { $status = 'okay'; }
        elsif ($_ =~ /Access Denied/)      { $status = 'access denied'; }
        elsif ($_ =~ /Bad Credentials/)    { $status = 'bad credentials'; }
        elsif ($_ =~ /Bad CGI/)            { $status = 'bad cgi'; }
        elsif ($_ =~ /Duplicate File/)     { $status = 'dupe file'; }
        elsif ($_ =~ /Duplicate Filename/) { $status = 'dupe name'; }
        else                               { $status = 'unknown'; }
    }

    return $status;
}

# prints the navigation bar
sub print_nav($$$) {
    my ($page, $page_count, $view_nws) = @_;
    my $prev_page = $page - 1;
    my $next_page = $page + 1;

    my $nws = 'nws=true';
    my $nwstext = '<a href=".';

    if ($page > 1) {
        $nwstext .= "?page=$page";
    }

    if (not $view_nws) {
        $nwstext .= '?' if ($page == 1);
        $nwstext .= '&amp;' if ($page > 1);
        $nwstext .= "$nws\">View NWS images</a>";
    }
    else {
        $nwstext .= '">View worksafe images</a>';
    }

    # create links to other pages
    my $ftext = 'First';
    my $ptext = 'Previous';
    my $ntext = 'Next';
    my $ltext = 'Last';

    unless ($page == 1) {
        if ($view_nws) {
            $ftext = "<a href=\".?$nws\">$ftext</a>";
            $ptext = "<a href=\".?page=$prev_page&amp;$nws\">$ptext</a>";
        }
        else {
            $ftext = "<a href=\".\">$ftext</a>";
            $ptext = "<a href=\".?page=$prev_page\">$ptext</a>";
        }
    }

    unless ($page == $page_count) {
        if ($view_nws) {
            $ntext = "<a href=\".?page=$next_page&amp;$nws\">$ntext</a>";
            $ltext = "<a href=\".?page=$page_count&amp;$nws\">$ltext</a>";
        }
        else {
            $ntext = "<a href=\".?page=$next_page\">$ntext</a>";
            $ltext = "<a href=\".?page=$page_count\">$ltext</a>";
        }
    }

    # print out the html
    print <<END;
        <div class="pagenav">
            $nwstext<br />
            $ftext
            $ptext
            $ntext
            $ltext<br />

END

    for (my $i = 1; $i <= $page_count; $i++) {
        if ($i == $page) {
            print "            $i\n";
        }
        else {
            print "            <a href=\".?page=$i";
            print "&amp;$nws" if ($view_nws);
            print "\">$i</a>\n";
        }
    }

    print "        </div>\n";
}

# prints the "upload a new image" form
sub print_upload_form($) {
    my ($user) = @_;
    my $upload = HBW_UPLOAD

    print <<END;
        <form action="$upload" method="post" enctype="multipart/form-data">
            <p>
                <input type="file" name="file" /><br />
                <input type="text" name="filename" /> New filename (optional)<br />
                <input type="text" name="name" /> Display name (optional)<br />
                <input type="checkbox" name="nws" /> Not worksafe?<br />
                <input type="hidden" name="username" value="$user" />
                <input type="submit" name="do_upload" value="Upload" />
            </p>
        </form>

END
}

# prints the current page of images
sub print_images($$$$) {
    my ($dbh, $page, $view_nws, $can_alter) = @_;
    my $img_url = HBW_IMG_URL;

    # calculate image offset in database
    my $offset = int(16 * ($page - 1));

    # fetch image set from database
    my $sth = $dbh->prepare("SELECT * FROM images ORDER BY id DESC LIMIT $offset, 16");
    $sth->execute();

    my $i = 0;
    print "        <table class=\"images\">\n";
    while (my $result = $sth->fetchrow_hashref()) {
        my $id = $result->{'id'};
        my $nws = $result->{'nws'};
        my $thumb = ($nwsn and not $view_nws) ? 'nws.png' : $result->{'thumbnail'};
        my $name = $result->{'name'};
        my $fname = $result->{'filename'};
        $fname = "<span class=\"nws\">$fname</span>" if ($nws);
        my $dims = $result->{'width'} . 'x' . $result->{'height'};
        my $size = pretty_size($result->{'size'});

        # generate edit form if the user has permission
        my $edit = '';
        if ($can_alter) {
            my $modify = LBW_MODIFY;
            $edit .= "\n";
            $edit .= "                    ";
            $edit .= "<form action=\"$modify\" method=\"post\">\n";
            $edit .= "                        ";
            $edit .= "<p>\n";
            $edit .= "                            ";
            $edit .= "<input type=\"hidden\" name=\"image\" value=\"$id\" />\n";
            $edit .= "                            ";
            $edit .= "<select name=\"action\">\n";
            $edit .= "                                ";
            $edit .= "<option value=\"nil\">-- Edit File</option>\n";
            $edit .= "                                ";
            $edit .= "<option value=\"delete\">Delete</option>\n";
            $edit .= "                                ";
            $edit .= "<option value=\"make_thumbnail\">Make Thumbnail</option>\n";
            $edit .= "                            ";
            $edit .= "</select>\n";
            $edit .= "                            ";
            $edit .= "<input type=\"submit\" value=\"Update\" />\n";
            $edit .= "                        ";
            $edit .= "</p>\n";
            $edit .= "                    ";
            $edit .= "</form>\n";
        }

        # start a new table row every 4 images
        if ($i % 4 == 0) {
            print "            <tr>\n";
        }

        print <<END;
                <td>
                    <a href="view.pl?image=$id"><img src="$img_url/$thumb" alt="$name" /></a><br />
                    $filename<br />
                    $dims $size$edit
                </td>
END

        # close the table row every 4 images
        if ($i % 4 == 3) {
            print "            </tr>\n";
        }

        $i += 1;
    }
    $sth->finish();

    # close the table row if it hasn't been done yet
    if ($i % 4 != 0) {
        print "            </tr>\n";
    }

    # display a blank table row if there were no images in the database
    if ($i == 0) {
        print <<END;
            <tr>
                <td>no images found</td>
            </tr>
END
    }

    # close the table
    print "        </table>\n";
}

# display an image and its information
sub print_image_view(@) {
    my (($hash, $name, $fname, $thumb, $width, $height, $size)) = @_;
    my $pretty_size = pretty_size($size);
    my $dims = "$width x $height";
    if ($height > 600 or $width > 800) {
        $dims = "<span class=\"oversized\">$dims</span>";
    }
    my $img_url = HBW_IMG_URL;

    print <<END;
        <table class="stats">
            <tr>
                <th colspan="2">Image Information</th>
            </tr>
            <tr>
                <td>Image:</td>
                <td><a href="$img_url/$fname">$img_url/$fname</a></td>
            </tr>
            <tr>
                <td>Name:</td>
                <td>$name</td>
            </tr>
            <tr>
                <td>Hash (SHA-512):</td>
                <td>$hash</td>
            </tr>
            <tr>
                <td>Dimensions:</td>
                <td>$dims</td>
            </tr>
            <tr>
                <td>Size:</td>
                <td>$pretty_size ($size bytes)</td>
            </tr>
            <tr>
                <td>HTML</td>
                <td>&lt;img src="$img_url/$fname" alt="$name" /&gt;</td>
            </tr>
            <tr>
                <td>BBCode</td>
                <td>[img]$img_url/$fname\[/img]</td>
            </tr>
END

    # display thumbnail code if needed
    if ($fname ne $thumb) {
        print <<END;
            <tr>
                <td>Thumbnail (HTML)</td>
                <td>&lt;a href="$img_url/$fname"&gt;&lt;img src="$img_url/$thumb" alt="$name" title="Thumbnail: Click for full" style="border: 1px solid #000;" /&gt;&lt;/a&gt;</td>
            </tr>
            <tr>
                <td>Thumbnail (BBCode)</td>
                <td>[url=$img_url/$fname][img]$img_url/$thumb\[/img][/url]</td>
            </tr>
        </table>

        <p>
            <img src="$img_url/$thumb" alt="$name" />
        </p>

END
    }
    else {
        print "        </table>\n\n";
    }

    # print image
    print <<END;
        <p>
            <img src="$img_url/$fname" alt="$name" />
        </p>
END
}

1;
